package com.blue.base.web.config;

import com.alibaba.fastjson.JSON;
import com.blue.base.common.enums.ServiceEnum;
import com.blue.base.common.bean.resp.JsonResult;
import com.blue.base.web.bean.DefineErrorAttributes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Optional;

/**
 * 基础异常处理器，主要是处理filter异常[无法被controller异常处理器处理的]
 * 加载机制：如果我们不自己实现异常处理机制，那么Spring将注入使用默认的异常处理对象BasicErrorController
 *
 * @author liulei
 * @version 1.0
 * @see org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration#basicErrorController
 */
@Configuration
@RestController
public class BasicErrorsHandler extends BasicErrorController implements BeanPostProcessor {

    /**
     * 构造方法【Important】
     */
    public BasicErrorsHandler() {
        super(new DefineErrorAttributes(), new ErrorProperties());
    }

    private static Logger log = LoggerFactory.getLogger(BasicErrorsHandler.class);

    private static final String DEFAULT_ERROR_BEAN = "basicErrorController";

    @Autowired
    private DefaultListableBeanFactory beanFactory;

    /**
     * 下列代码可以被：
     * @AutoConfigureBefore(ErrorMvcAutoConfiguration.class)注解完全代替，控制好加载时机即可
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        boolean containsBean = beanFactory.containsBean(DEFAULT_ERROR_BEAN);
        if (containsBean) {
            //移除默认bean的定义和实例
            log.info("移除spring默认处理异常bean，使用自定义bean=BasicErrorsHandler");
            beanFactory.removeBeanDefinition(DEFAULT_ERROR_BEAN);
        }
        return bean;
    }

    @Override
    @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
        String message = String.valueOf(body.get("message"));
        // 优先判断是否是过滤器中的自定义异常
        HttpStatus status = getStatus(request);
        Object code = Optional.ofNullable(body.get("code")).orElse(status.value());
        JsonResult failed = JsonResult.define(ServiceEnum.USER, (Integer) code, message);
        return new ResponseEntity(JSON.toJSONString(failed), HttpStatus.OK);
    }
}
